from nonebot import *
from nonebot.log import logger
import docker
import aiocqhttp

bot = get_bot()
client = docker.DockerClient(base_url='unix://var/run/docker.sock', timeout=30)


def _ctx_to_name(ctx):
    if ctx['message_type'] == 'group':
        return f"qzone-{ctx['group_id']}-{ctx['sender']['user_id']}"
    elif ctx['message_type'] == 'private':
        return f"qzone-{ctx['sender']['user_id']}"


async def _resp(message_type, group_id, user_id, msg):
    if msg == '':
        msg = ' '
    if len(msg) > 1000:
        msg = msg[:1000]+'\n...'
    if message_type == 'private':
        await bot.send_private_msg(user_id=user_id, message=msg)
    if message_type == 'group':
        await bot.send_group_msg(group_id=group_id, message=f'[CQ:at,qq={user_id}]\n{msg}')


def _analyze_ctx(ctx):
    group_id = ''
    if ctx.get('group_id'):
        group_id = ctx['group_id']
    return ctx['message_type'], group_id, ctx['user_id'], _ctx_to_name(ctx), ctx['message'][0]['data']['text']


async def reboot(ctx):
    message_type, group_id, user_id, name, _ = _analyze_ctx(ctx=ctx)
    client.api.restart(container=name)
    await _resp(message_type, group_id, user_id, "重启完成")


async def clean(ctx):
    message_type, group_id, user_id, name, _ = _analyze_ctx(ctx=ctx)
    if len(client.containers.list(filters={"name": name})) == 0:
        await _resp(message_type, group_id, user_id, "你还没有创建容器")
        return
    client.api.remove_container(container=name, force=True)
    await _resp(message_type, group_id, user_id, "清理完成")


async def run(ctx):
    message_type, group_id, user_id, name, text = _analyze_ctx(ctx=ctx)
    command = str(text).split(sep=" ", maxsplit=1)[1]
    if len(client.containers.list(filters={"name": name})) == 0:
        await _resp(message_type, group_id, user_id, "你还没有创建容器")
        return
    code, result = client.containers.get(container_id=name).exec_run(cmd="sh -c \"" + command + "\"", privileged=True)
    await _resp(message_type, group_id, user_id, bytes.decode(result))


async def create(ctx):
    message_type, group_id, user_id, name, _ = _analyze_ctx(ctx=ctx)
    if len(client.containers.list(filters={"name": name})) > 0:
        await _resp(message_type, group_id, user_id, "你已经创建容器")
        return
    client.containers.run(image='alpine', name=name, tty=True, stdin_open=True, detach=True,
                          volumes={'/Users/sgcx201/qzone/' + name: {'bind': '/root', 'mode': 'rw'}},
                          entrypoint='sh')
    await _resp(message_type, group_id, user_id, "创建成功")


async def helper(ctx):
    message_type, group_id, user_id, _, _ = _analyze_ctx(ctx=ctx)
    await _resp(message_type, group_id, user_id, """
    版本:测试版,大家的所有内容会在正式版上线时被清空
    简介:这是一个以qq群号+qq号或私聊时的qq号区分的容器🐔器人,你可以对你的容器做任何事情
    源码:https://gitee.com/tiddar/bot
    术语: 
        空间: 我的电脑会被大家瓜分,每个人与机器人私聊会分成一个单独的空间,里面的文件/内存/网络等会被隔离,称这个空间为私聊空间,对应的，在qq群发命令会分出来一个以"qq群号+qq号"来唯一标识的你的qq群空间
        空间号: 私聊空间的空间号为你的QQ号,QQ群里你的空间的的空间号为"qq群号-qq号"
    命令:
    create: 创建一个容器,如果已经在对应空间（qq群+qq号）或私聊空间创建过容器便会失败,你可以指定容器的操作系统,默认为alpine，一个轻量的linux，基本啥都没有，想装自己装吧
    同时,容器只会保留/root目录下的文件
        每次重启时都会重置其他文件夹内容,请谨慎使用
        每次重启时都会重置其他文件夹内容,请谨慎使用
        每次重启时都会重置其他文件夹内容,请谨慎使用
    clean: 销毁容器,不可逆
    reboot: 重启容器，请做好备份工作
    run [command..]: 跑一些shell命令,可以利用这个命令做很多事情,对应的输出也会发到对应的QQ群里,没钱买pro,不要想色图惹,每次都会在/root下执行,cd啥的就不要搞了。。
    快实现: file [qq群号] password: 用于管理(上传下载）文件,必须先设置密码,才可访问,可以不写qq群号来访问私聊空间的文件,访问的路径 空间号.bot.tiddar.com:81
    未实现: expose [port]: 暴露一个端口, 暴露后可以通过 端口.群号.QQ号.bot.tiddar.com:81 访问此端口,此操作会重启容器,请做好备份工作,有些复杂,安全性也比较难搞,过段时间再整
    """)


cmd = {
    "create": create,
    "run": run,
    # "expose": expose,
    "reboot": reboot,
    "clean": clean,
    "help": helper
}

worker = {}


# {
#     'anonymous': None,
#     'font': 10159576,
#     'group_id': 399188082,
#     'message': [
#         {
#             'type': 'text',
#             'data': {
#                 'text': '写写加瓦还打算更新吗'
#             }
#         },
#         {
#             'type': 'face',
#             'data': {
#                 'id': '178'
#             }
#         }
#     ],
#     'message_id': 11,
#     'message_type': 'group',
#     'post_type': 'message',
#     'raw_message': '写写加瓦还打算更新吗[
#         CQ: face,
#         id=178
#     ]',
#     'self_id': 2921225730,
#     'sender': {
#         'age': 19,
#         'area': '北京',
#         'card': '红黑树',
#         'level': '传说',
#         'nickname': '.',
#         'role': 'member',
#         'sex': 'male',
#         'title': '',
#         'user_id': 1790931015
#     },
#     'sub_type': 'normal',
#     'time': 1586573267,
#     'user_id': 1790931015
# }


@bot.on_message
async def handle(ctx: aiocqhttp.Event):
    if ctx.get('message') and len(ctx['message']) == 1 and ctx['message'][0]['type'] == 'text':
        text = ctx['message'][0]['data']['text']
        cmds = str(text).split(' ')
        if cmd.get(cmds[0]):
            await cmd[cmds[0]](ctx)
